<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>为什么getElementsByTagName比querySelectorAll方法快 | 砖业洋__</title>
    <meta name="generator" content="VuePress 1.5.2">
    <link rel="icon" href="/haizei.jpg">
    <meta name="description" content="">
    <link rel="preload" href="/assets/css/0.styles.1f351a1e.css" as="style"><link rel="preload" href="/assets/js/app.1c226385.js" as="script"><link rel="preload" href="/assets/js/2.5bd328db.js" as="script"><link rel="preload" href="/assets/js/3.90e623d3.js" as="script"><link rel="preload" href="/assets/js/5.9f70a21c.js" as="script"><link rel="prefetch" href="/assets/js/10.4eb1cc28.js"><link rel="prefetch" href="/assets/js/11.cd070e67.js"><link rel="prefetch" href="/assets/js/12.0c5442fd.js"><link rel="prefetch" href="/assets/js/4.3a00ff1b.js"><link rel="prefetch" href="/assets/js/6.db1982cd.js"><link rel="prefetch" href="/assets/js/7.46572acb.js"><link rel="prefetch" href="/assets/js/8.2b398bc4.js"><link rel="prefetch" href="/assets/js/9.f2979413.js">
    <link rel="stylesheet" href="/assets/css/0.styles.1f351a1e.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><!----> <!----> <header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/haizei.jpg" alt="砖业洋__" class="logo"> <span class="site-name can-hide">砖业洋__</span></a> <div class="links"><span>你好，砖业洋__持续为你分享    </span> <div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><a href="https://liuchenyang0515.blog.csdn.net" target="_blank" rel="noopener noreferrer" class="nav-link external">
  CSDN主页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link">
  首页
</a></div><div class="nav-item"><a href="https://liuchenyang0515.blog.csdn.net" target="_blank" rel="noopener noreferrer" class="nav-link external">
  CSDN主页
  <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>为什么getElementsByTagName比querySelectorAll方法快</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/tech/%E4%B8%BA%E4%BB%80%E4%B9%88getElementsByTagName%E6%AF%94querySelectorAll%E6%96%B9%E6%B3%95%E5%BF%AB.html#htmlcollection与nodelist的区别" class="sidebar-link">HTMLCollection与NodeList的区别</a><ul class="sidebar-sub-headers"></ul></li><li><a href="/tech/%E4%B8%BA%E4%BB%80%E4%B9%88getElementsByTagName%E6%AF%94querySelectorAll%E6%96%B9%E6%B3%95%E5%BF%AB.html#实时-live-的nodelist和静态-static-的nodelist" class="sidebar-link">实时(live)的NodeList和静态(static)的NodeList</a><ul class="sidebar-sub-headers"></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="为什么getelementsbytagname比queryselectorall方法快"><a href="#为什么getelementsbytagname比queryselectorall方法快" class="header-anchor">#</a> 为什么getElementsByTagName比querySelectorAll方法快</h1> <blockquote><p>作者：dreamapple | 技术风暴</p></blockquote> <p>最近准备把JavaScript的许多原生API都研究一下，恰巧昨天在看<code>querySelectorAll</code>方法的时候看到了一篇文章<a href="https://www.nczonline.net/blog/2010/09/28/why-is-getelementsbytagname-faster-that-queryselectorall/" target="_blank" rel="noopener noreferrer">Why is getElementsByTagName() faster than querySelectorAll()?<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，这篇文章解释了为什么<code>getElementsByTagName</code>方法比<code>querySelectorAll</code>方法快的原因，如果你英语不错的话，推荐你看看原文。当然如果你不想看的话，继续把这篇文章看完也是可以得到答案的。</p> <p>在看到那篇文章之前，我对这方面也没有深入的了解过；所以决定花费一番功夫好好地探究一下。首先在开始之前，我们要先做一些基本的功课：<br> <br></p> <h2 id="htmlcollection与nodelist的区别"><a href="#htmlcollection与nodelist的区别" class="header-anchor">#</a> <code>HTMLCollection</code>与<code>NodeList</code>的区别</h2> <br> <p><code>HTMLCollection</code>和<code>NodeList</code>都是<code>DOM</code>的节点集合；但是它们两个能够包含的元素是不太一样的，<code>HTMLCollection</code>只可以包含<code>HTML</code>元素(<code>Element</code>)集合，<code>NodeList</code>可以包含任意的节点类型，就是说<code>NodeList</code>不仅可以包含<code>HTML</code>元素集合，也可以包含像文字节点，注释节点等类型的节点集合。 我们可以看下面一个例子：</p> <div class="language-html extra-class"><pre class="language-html"><code><span class="token comment">&lt;!-- HTML部分 --&gt;</span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>test<span class="token punctuation">&quot;</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>test<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- 注释部分 --&gt;</span>
    测试用例
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">&gt;</span></span>p标签内容<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>form1<span class="token punctuation">&quot;</span></span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>#<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- username --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username1<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        用户名：
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username1<span class="token punctuation">&quot;</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- password --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password1<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        密码：
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password1<span class="token punctuation">&quot;</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>form2<span class="token punctuation">&quot;</span></span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>#<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- username --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username2<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        用户名：
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>username2<span class="token punctuation">&quot;</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
    <span class="token comment">&lt;!-- password --&gt;</span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password2<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
        密码：
        <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>password2<span class="token punctuation">&quot;</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">&quot;</span>text<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token comment">// NodeList</span>
<span class="token keyword">let</span> test <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'test'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> nodeList <span class="token operator">=</span> test<span class="token punctuation">.</span>childNodes<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>nodeList<span class="token punctuation">,</span> nodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
  
<span class="token comment">// HTMLCollection</span>
<span class="token keyword">let</span> allForms <span class="token operator">=</span> document<span class="token punctuation">.</span>forms<span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>allForms<span class="token punctuation">,</span> allForms<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>我们看一下控制台的输出结果：<br> <br> <img src="/assets/img/whygetelement_1.79de8c2d.png" alt="NodeList和HTMLCollection的区别"> <center style="color:#999;font-size:0.9em;">NodeList和HTMLCollection的区别</center> <br>
我们可以看到，<code>nodeList</code>是一个<code>NodeList</code>集合，它包含了3个<code>text</code>节点，一个<code>comment</code>节点和一个p元素节点；<code>allForms</code>是一个<code>HTMLCollection</code>集合，它只包含了两个<code>form</code>元素。<br>
它们两个之间还有一个不同，那就是<code>HTMLCollection</code>比<code>NodeList</code>多提供了一个<code>namedItem</code>方法，其它的方法它们两个都是相同的。当然，这里只是简单的把他们的不同点列举了出来，如果大家还想深入的了解它们，可以参考下面的资料：</p> <ul><li><a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList" target="_blank" rel="noopener noreferrer">NodeList<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection" target="_blank" rel="noopener noreferrer">HTMLCollection<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li><a href="https://dom.spec.whatwg.org/#concept-collection" target="_blank" rel="noopener noreferrer">DOM4 specification - Collections<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a><br> <br></li></ul> <h2 id="实时-live-的nodelist和静态-static-的nodelist"><a href="#实时-live-的nodelist和静态-static-的nodelist" class="header-anchor">#</a> 实时(<code>live</code>)的NodeList和静态(<code>static</code>)的NodeList</h2> <br> <ul><li>关于<code>Live</code>NodeLists在<code>W3C</code>上面的原文解释是这样的：</li></ul> <blockquote><p><code>NodeList</code> and <code>NamedNodeMap</code> objects in the DOM are <code>live</code>; that is, changes to the underlying document structure are <code>reflected</code> in all relevant NodeList and NamedNodeMap objects. For example, if a DOM user gets a NodeList object containing the children of an Element, then subsequently adds more children to that element (or removes children, or modifies them), those changes are <code>automatically reflected</code> in the NodeList, without further action on the user's part. Likewise, changes to a Node in the tree are reflected in all references to that Node in NodeList and NamedNodeMap objects.</p></blockquote> <p>上面的大概意思就是说，<code>DOM</code>中的<code>NodeList</code>是一种特殊的对象，它是实时更新的；就是你对这个<code>NodeList</code>中的<code>任何一个元素</code>进行的一些操作，都会实时的更新到这个<code>NodeList</code>对象上面。我们下面可以来实践一下：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">let</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> liveNodeList <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>liveNodeList<span class="token punctuation">,</span> liveNodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> p <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">'test'</span><span class="token punctuation">;</span>
body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>liveNodeList<span class="token punctuation">,</span> liveNodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>你可以将上面的代码粘贴到浏览器空白页的控制台里，运行一下；然后你就会看到下面奇怪的结果：<br> <br> <img src="/assets/img/whygetelement_2.c3c41f75.png" alt="实时的HTMLCollection集合"> <center style="color:#999;font-size:0.9em;">实时的HTMLCollection集合</center> <br>
这充分说明了我们获取的<code>liveNodeList</code>是一个实时的<code>NodeList</code>或者说<code>HTMLCollection</code>,当我们第一次打印<code>liveNodeList</code>的时候，它确实是一个<code>length</code>属性为0的集合，也就是说，这个时候这个集合里面是没有元素的；但是经过后面的操作，我们添加了一个<code>p</code>元素，这个操作会实时的反映到这个对象身上。然后就会出现了上面的那种情况。<br> <br></p> <ul><li>关于<code>Static</code>NodeLists在<code>W3C</code>上面的原文解释如下：</li></ul> <blockquote><p>The <code>NodeList</code> object returned by the <code>querySelectorAll()</code> method must be static, not live ([DOM-LEVEL-3-CORE], section 1.1.1). Subsequent changes to the structure of the underlying document must not be reflected in the <code>NodeList</code> object. This means that the object will instead contain a list of matching <code>Element</code> nodes that were in the document at the time the list was created.</p></blockquote> <p>上面的大概意思就是说，通过使用<code>querySelectorAll()</code>方法返回的<code>NodeList</code>集合必须是静态的，就是一旦获取到这个结果；那么这个结果不会因为后面再对这个集合中元素进行的操作而进行改变。我们可以改变一下上面的例子：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">let</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 使用querySelectorAll方法</span>
<span class="token keyword">let</span> liveNodeList <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>liveNodeList<span class="token punctuation">,</span> liveNodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> p <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
p<span class="token punctuation">.</span>innerText <span class="token operator">=</span> <span class="token string">'test'</span><span class="token punctuation">;</span>
body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>p<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>liveNodeList<span class="token punctuation">,</span> liveNodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 再次使用querySelectorAll获取p元素集合</span>
liveNodeList <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'p'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>liveNodeList<span class="token punctuation">,</span> liveNodeList<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>你可以再次将上面的代码粘贴到浏览器的控制台里，运行一下；然后就会得到下面的结果：<br> <br> <img src="/assets/img/whygetelement_3.747c75e4.png" alt="静态的NodeList集合"> <center style="color:#999;font-size:0.9em;">静态的NodeList集合</center> <br>
  上面这张图片展示的结果跟我们的预期是一样的，也就是说，静态的<code>NodeList</code>集合，一旦获取到结果，就不会再次因为这个集合中的元素发生变化而发生改变。<br> <br>
到目前为止，我们已经把一些需要我们了解的知识简单的了解了一下，下面我们来解释为什么getElementsByTagName比querySelectorAll方法快的原因。因为通过<code>getElementsByTagName</code>获取到的<code>NodeList</code>是一个实时的集合，这种实时的集合，是不需要在一开始的时候就获取到所有的信息的；然而通过<code>querySelectorAll</code>方法获取到的的<code>NodeList</code>集合是一个静态的集合，这个集合相当于一个快照，就是在这个方法运行的那个时间，它所要获取的集合元素的一个快照，所以这个集合要保存大量的信息，速度自然会慢下来。</p> <p>为了加深理解，我们可以这样理解：<strong>使用getElementsByTagName方法我们得到的结果就像是一个对象的索引，而通过querySelectorAll方法我们得到的是一个对象的克隆；所以当这个对象数据量非常大的时候，显然克隆这个对象所需要花费的时间是很长的。</strong></p> <p>当然，真实的原因是因为这两个方法底层的代码实现是不一样的；实时的NodeList集合底层的代码是<a href="http://trac.webkit.org/browser/trunk/WebCore/dom/DynamicNodeList.cpp" target="_blank" rel="noopener noreferrer">DynamicNodeList.cpp<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，静态的NodeList集合底层的代码是<a href="http://trac.webkit.org/browser/trunk/WebCore/dom/StaticNodeList.cpp" target="_blank" rel="noopener noreferrer"> StaticNodeList.cpp<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>。</p> <p>这也给我们一些启示，在以后需要用到获取元素集合的方法的时候，我们就要根据不同的场景来选择使用不同的方法了。如果你不需要一个快照，那就选择使用<code>getElementsByTagName</code>方法，如果你需要一个快照来进行复杂的CSS查询，或者复杂的DOM操作的话，那就选择使用<code>querySelectorAll</code>方法。</p> <p>虽然道理明白了，但是我们还是要验证一下；结果到底是不是和我们想的那样呢？毕竟实践出真知呀，所以我们还要写个例子来测试一下：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">let</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">1e3</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> a <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    a<span class="token punctuation">.</span>innerText <span class="token operator">=</span> i<span class="token punctuation">;</span>
    body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">time</span><span class="token punctuation">(</span><span class="token string">'getElementsByTagName: '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> l1 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">timeEnd</span><span class="token punctuation">(</span><span class="token string">'getElementsByTagName: '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">time</span><span class="token punctuation">(</span><span class="token string">'querySelectorAll: '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> l2 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">timeEnd</span><span class="token punctuation">(</span><span class="token string">'querySelectorAll: '</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>当我们向文档中添加1e3(1000)个<code>a</code>标签的时候，控制台打印的结果如下：</p> <p><img src="/assets/img/whygetelement_4.00810534.png" alt="获取文档中1000个a标签"> <center style="color:#999;font-size:0.9em;">获取文档中1000个a标签</center> <br>
当我们向文档中添加1e4(10000)个<code>a</code>标签的时候，控制台的打印结果如下：<br> <br> <img src="/assets/img/whygetelement_5.78e45763.png" alt="获取文档中10000个a标签"> <center style="color:#999;font-size:0.9em;">获取文档中10000个a标签</center></p> <p>通过上面的结果我们可以看到，随着<code>a</code>标签的数量增加，使用<code>querySelectorAll</code>方法的速度变得越来越慢，而使用<code>getElementsByTagName</code>方法速度变化并没有很大；大家也可以自己实践一下，看看结果。<br> <br>
还有一点其实是需要我们注意的，我们使用的<code>console.time</code>和<code>console.timeEnd</code>方法得出来的时间并不是特别准确的；更准确的做法是使用<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Performance" target="_blank" rel="noopener noreferrer"><code>Performance</code><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>这个对象提供的<a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Performance/now" target="_blank" rel="noopener noreferrer"><code>now</code><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>方法来进行计时。这里有一些文章关于为什么要使用<code>Performance</code>的解释：<a href="http://blog.teamtreehouse.com/timing-javascript-code-high-resolution-timestamps" target="_blank" rel="noopener noreferrer">Timing JavaScript Code with High Resolution Timestamps<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>和<a href="https://www.sitepoint.com/discovering-the-high-resolution-time-api/" target="_blank" rel="noopener noreferrer">Discovering the High Resolution Time API<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>，接下来我们来修改一下上面的代码：</p> <div class="language-javascript extra-class"><pre class="language-javascript"><code><span class="token keyword">let</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'body'</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">1e3</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> a <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    a<span class="token punctuation">.</span>innerText <span class="token operator">=</span> i<span class="token punctuation">;</span>
    body<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>a<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> t0 <span class="token operator">=</span> window<span class="token punctuation">.</span>performance<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> l1 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementsByTagName</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> t1 <span class="token operator">=</span> window<span class="token punctuation">.</span>performance<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> t2 <span class="token operator">=</span> window<span class="token punctuation">.</span>performance<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> l2 <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> t3 <span class="token operator">=</span> window<span class="token punctuation">.</span>performance<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;getElementsByTagName方法使用了&quot;</span> <span class="token operator">+</span> <span class="token punctuation">(</span>t1 <span class="token operator">-</span> t0<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot;毫秒.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;querySelectorAll方法使用了&quot;</span> <span class="token operator">+</span> <span class="token punctuation">(</span>t3 <span class="token operator">-</span> t2<span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token string">&quot;毫秒.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>我们运行一下上面的代码，反别试一下向页面添加1e3，1e4，1e5个<code>a</code>标签时候，这两个方法执行时间的快慢。</p> <p><img src="/assets/img/whygetelement_6.842f912a.png" alt="获取文档中1000个a标签"> <center style="color:#999;font-size:0.9em;">获取文档中1000个a标签</center> <br> <img src="/assets/img/whygetelement_7.f8657865.png" alt="获取文档中10000个a标签"> <center style="color:#999;font-size:0.9em;">获取文档中10000个a标签</center> <br> <img src="/assets/img/whygetelement_8.612ad96d.png" alt="获取文档中100000个a标签"><br> <center style="color:#999;font-size:0.9em;">获取文档中100000个a标签</center> <br>
通过上面的结过，我们可以清楚地看到，随着<code>a</code>标签数量的增多，使用<code>querySelectorAll</code>方法会越来越慢，而使用<code>getElementsByTagName</code>方法的速度却变化不大，这也说明了<code>getElementsByTagName</code>方法确实比<code>querySelectorAll</code>方法要快。<br> <br>
到这里，我们要说明的东西基本上也就说完了；其实关于这两个方法的比较，可以在<a href="https://jsperf.com/" target="_blank" rel="noopener noreferrer">jsPerf<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>得到权威一点的比较，大家可以看看<a href="https://jsperf.com/getelementsby-vs-queryselectorall/7" target="_blank" rel="noopener noreferrer">getElementsBy* vs querySelectorAll<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a>上面的比较结果，很直观。</p> <p><img src="/assets/img/whygetelement_9.884dc1ee.png" alt="jsPerf上面的测试结果: Ops/Sec是指每秒执行操作的次数，越高越好"> <center style="color:#999;font-size:0.9em;">jsPerf上面的测试结果: Ops/Sec是指每秒执行操作的次数，越高越好 </center> <br>
参考的一些资料：</p> <ul><li><a href="https://stackoverflow.com/questions/15763358/difference-between-htmlcollection-nodelists-and-arrays-of-objects" target="_blank" rel="noopener noreferrer">Difference between HTMLCollection, NodeLists, and arrays of objects<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li> <li><a href="https://www.nczonline.net/blog/2010/09/28/why-is-getelementsbytagname-faster-that-queryselectorall/" target="_blank" rel="noopener noreferrer">Why is getElementsByTagName() faster than querySelectorAll()?<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></li></ul> <br> <!----></div> <footer class="page-edit"><!----> <!----></footer> <!----> </main></div><div class="global-ui"></div></div>
    <script src="/assets/js/app.1c226385.js" defer></script><script src="/assets/js/2.5bd328db.js" defer></script><script src="/assets/js/3.90e623d3.js" defer></script><script src="/assets/js/5.9f70a21c.js" defer></script>
  </body>
</html>
